home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / bombs9.zip / WEAPONS.QC < prev   
Text File  |  1996-10-15  |  44KB  |  1,920 lines

  1. /*
  2.  
  3. Bouncing Fragmentation Grenade!    7/28/96 by Steve Bond
  4. Email: wedge@nuc.net    WWW: http://www.nuc.net/quake
  5.  
  6. >>>READ THE README!
  7.  
  8. Hey ID! 
  9. If you are reading this, PUH-LEEZE fly me and John to Texas!
  10. We'll scrub the shitters at id for the chance to shake hands!
  11. (I mean - we'll wash our hands first and everything)
  12.  
  13. */
  14.  
  15. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  16. void () player_run;
  17. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  18. void(vector org, vector vel, float damage) SpawnBlood;
  19. void() SuperDamageSound;
  20.  
  21. float bombtimer;
  22.  
  23.  
  24. void() W_FireBomb;
  25. void() BombTouch;
  26. void() BombExplode;
  27. void() BombExplosion;
  28. void() ShrapnelExplode;
  29. void() BombTime;
  30. void() W_FireGIBGUN;
  31. void() T_GIBTouch;
  32. void() GIBExplode;
  33. void() W_FireFLASH;
  34. void() T_FlashTouch;
  35.  
  36. // called by worldspawn
  37. void() W_Precache =
  38. {
  39.     precache_sound ("weapons/r_exp3.wav");  // new rocket explosion
  40.     precache_sound ("weapons/rocket1i.wav");        // spike gun
  41.     precache_sound ("weapons/sgun1.wav");
  42.     precache_sound ("weapons/guncock.wav"); // player shotgun
  43.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  44.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  45.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  46.     precache_sound ("weapons/spike2.wav");  // super spikes
  47.     precache_sound ("weapons/tink1.wav");   // spikes tink (used in c code)
  48.     precache_sound ("weapons/grenade.wav"); // grenade launcher
  49.     precache_sound ("weapons/bounce.wav");          // grenade bounce
  50.     precache_sound ("weapons/shotgn2.wav"); // super shotgun
  51.     precache_sound ("items/damage2.wav");
  52.     precache_sound ("player/tornoff2.wav");
  53.     precache_sound ("player/lburn1.wav");
  54.     precache_sound ("doors/airdoor2.wav");
  55.  
  56.  
  57. };
  58.  
  59. float() crandom =
  60. {
  61.     return 2*(random() - 0.5);
  62. };
  63.  
  64. /*
  65. ================
  66. W_FireAxe
  67. ================
  68. */
  69. void() W_FireAxe =
  70. {
  71.     local   vector  source;
  72.     local   vector  org;
  73.  
  74.     source = self.origin + '0 0 16';
  75.     traceline (source, source + v_forward*64, FALSE, self);
  76.     if (trace_fraction == 1.0)
  77.         return;
  78.     
  79.     org = trace_endpos - v_forward*4;
  80.  
  81.     if (trace_ent.takedamage)
  82.     {
  83.         trace_ent.axhitme = 1;
  84.         SpawnBlood (org, '0 0 0', 20);
  85.         T_Damage (trace_ent, self, self, 20);
  86.     }
  87.     else
  88.     {       // hit wall
  89.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  90.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  91.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  92.         WriteCoord (MSG_BROADCAST, org_x);
  93.         WriteCoord (MSG_BROADCAST, org_y);
  94.         WriteCoord (MSG_BROADCAST, org_z);
  95.     }
  96. };
  97.  
  98.  
  99. //============================================================================
  100.  
  101.  
  102. vector() wall_velocity =
  103. {
  104.     local vector    vel;
  105.     
  106.     vel = normalize (self.velocity);
  107.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  108.     vel = vel + 2*trace_plane_normal;
  109.     vel = vel * 200;
  110.     
  111.     return vel;
  112. };
  113.  
  114.  
  115. /*
  116. ================
  117. SpawnMeatSpray
  118. ================
  119. */
  120. void(vector org, vector vel) SpawnMeatSpray =
  121. {
  122.     local   entity missile, mpuff;
  123.     local   vector  org;
  124.  
  125.     missile = spawn ();
  126.     missile.owner = self;
  127.     missile.movetype = MOVETYPE_BOUNCE;
  128.     missile.solid = SOLID_NOT;
  129.  
  130.     makevectors (self.angles);
  131.  
  132.     missile.velocity = vel;
  133.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  134.  
  135.     missile.avelocity = '3000 1000 2000';
  136.     
  137. // set missile duration
  138.     missile.nextthink = time + 1;
  139.     missile.think = SUB_Remove;
  140.  
  141.     setmodel (missile, "progs/zom_gib.mdl");
  142.     setsize (missile, '0 0 0', '0 0 0');            
  143.     setorigin (missile, org);
  144. };
  145.  
  146. /*
  147. ================
  148. SpawnBlood
  149. ================
  150. */
  151. void(vector org, vector vel, float damage) SpawnBlood =
  152. {
  153.     particle (org, vel*0.1, 73, damage*2);
  154. };
  155.  
  156. /*
  157. ================
  158. spawn_touchblood
  159. ================
  160. */
  161. void(float damage) spawn_touchblood =
  162. {
  163.     local vector    vel;
  164.  
  165.     vel = wall_velocity () * 0.2;
  166.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  167. };
  168.  
  169.  
  170. /*
  171. ================
  172. SpawnChunk
  173. ================
  174. */
  175. void(vector org, vector vel) SpawnChunk =
  176. {
  177.     particle (org, vel*0.02, 0, 10);
  178. };
  179.  
  180. /*
  181. ==============================================================================
  182.  
  183. MULTI-DAMAGE
  184.  
  185. Collects multiple small damages into a single damage
  186.  
  187. ==============================================================================
  188. */
  189.  
  190. entity  multi_ent;
  191. float   multi_damage;
  192.  
  193. void() ClearMultiDamage =
  194. {
  195.     multi_ent = world;
  196.     multi_damage = 0;
  197. };
  198.  
  199. void() ApplyMultiDamage =
  200. {
  201.     if (!multi_ent)
  202.         return;
  203.     T_Damage (multi_ent, self, self, multi_damage);
  204. };
  205.  
  206. void(entity hit, float damage) AddMultiDamage =
  207. {
  208.     if (!hit)
  209.         return;
  210.     
  211.     if (hit != multi_ent)
  212.     {
  213.         ApplyMultiDamage ();
  214.         multi_damage = damage;
  215.         multi_ent = hit;
  216.     }
  217.     else
  218.         multi_damage = multi_damage + damage;
  219. };
  220.  
  221. /*
  222. ==============================================================================
  223.  
  224. BULLETS
  225.  
  226. ==============================================================================
  227. */
  228.  
  229. /*
  230. ================
  231. TraceAttack
  232. ================
  233. */
  234. void(float damage, vector dir) TraceAttack =
  235. {
  236.     local   vector  vel, org;
  237.     
  238.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  239.     vel = vel + 2*trace_plane_normal;
  240.     vel = vel * 200;
  241.  
  242.     org = trace_endpos - dir*4;
  243.  
  244.     if (trace_ent.takedamage)
  245.     {
  246.         SpawnBlood (org, vel*0.2, damage);
  247.         AddMultiDamage (trace_ent, damage);
  248.     }
  249.     else
  250.     {
  251.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  252.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  253.         WriteCoord (MSG_BROADCAST, org_x);
  254.         WriteCoord (MSG_BROADCAST, org_y);
  255.         WriteCoord (MSG_BROADCAST, org_z);
  256.     }
  257. };
  258.  
  259. /*
  260. ================
  261. FireBullets
  262.  
  263. Used by shotgun, super shotgun, and enemy soldier firing
  264. Go to the trouble of combining multiple pellets into a single damage call.
  265. ================
  266. */
  267. void(float shotcount, vector dir, vector spread) FireBullets =
  268. {
  269.     local   vector direction;
  270.     local   vector  src;
  271.     
  272.     makevectors(self.v_angle);
  273.  
  274.     src = self.origin + v_forward*10;
  275.     src_z = self.absmin_z + self.size_z * 0.7;
  276.  
  277.     ClearMultiDamage ();
  278.     while (shotcount > 0)
  279.     {
  280.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  281.  
  282.         traceline (src, src + direction*2048, FALSE, self);
  283.         if (trace_fraction != 1.0)
  284.             TraceAttack (4, direction);
  285.  
  286.         shotcount = shotcount - 1;
  287.     }
  288.     ApplyMultiDamage ();
  289. };
  290.  
  291. /*
  292. ================
  293. W_FireShotgun
  294. ================
  295. */
  296. void() W_FireShotgun =
  297. {
  298.     local vector dir;
  299.  
  300.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); 
  301.  
  302.     self.punchangle_x = -2;
  303.     
  304.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  305.     dir = aim (self, 100000);
  306.     FireBullets (6, dir, '0.04 0.04 0');
  307. };
  308.  
  309.  
  310. /*
  311. ================
  312. W_FireSuperShotgun
  313. ================
  314. */
  315. void() W_FireSuperShotgun =
  316. {
  317.     local vector dir;
  318.  
  319.     if (self.currentammo == 1)
  320.     {
  321.         W_FireShotgun ();
  322.         return;
  323.     }
  324.         
  325.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM); 
  326.  
  327.     self.punchangle_x = -4;
  328.     
  329.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  330.     dir = aim (self, 100000);
  331.     FireBullets (14, dir, '0.14 0.08 0');
  332. };
  333.  
  334.  
  335. /*
  336. ==============================================================================
  337.  
  338. ROCKETS
  339.  
  340. ==============================================================================
  341. */
  342.  
  343. void()  s_explode1      =       [0,             s_explode2] {};
  344. void()  s_explode2      =       [1,             s_explode3] {};
  345. void()  s_explode3      =       [2,             s_explode4] {};
  346. void()  s_explode4      =       [3,             s_explode5] {};
  347. void()  s_explode5      =       [4,             s_explode6] {};
  348. void()  s_explode6      =       [5,             SUB_Remove] {};
  349.  
  350. void() BecomeExplosion =
  351. {
  352.     self.movetype = MOVETYPE_NONE;
  353.     self.velocity = '0 0 0';
  354.     self.touch = SUB_Null;
  355.     setmodel (self, "progs/s_explod.spr");
  356.     self.solid = SOLID_NOT;
  357.     s_explode1 ();
  358. };
  359.  
  360. void() T_MissileTouch =
  361. {
  362.     local float     damg;
  363.  
  364.     if (other == self.owner)
  365.         return;         // don't explode on owner
  366.  
  367.     if (pointcontents(self.origin) == CONTENT_SKY)
  368.     {
  369.         remove(self);
  370.         return;
  371.     }
  372.  
  373.     damg = 100 + random()*20;
  374.     
  375.     if (other.health)
  376.     {
  377.         if (other.classname == "monster_shambler")
  378.             damg = damg * 0.5;      // mostly immune
  379.         T_Damage (other, self, self.owner, damg );
  380.     }
  381.  
  382.     // don't do radius damage to the other, because all the damage
  383.     // was done in the impact
  384.     T_RadiusDamage (self, self.owner, 120, other);
  385.  
  386. //      sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  387.     self.origin = self.origin - 8*normalize(self.velocity);
  388.  
  389.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  390.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  391.     WriteCoord (MSG_BROADCAST, self.origin_x);
  392.     WriteCoord (MSG_BROADCAST, self.origin_y);
  393.     WriteCoord (MSG_BROADCAST, self.origin_z);
  394.  
  395.     BecomeExplosion ();
  396. };
  397.  
  398.  
  399.  
  400. /*
  401. ================
  402. W_FireRocket
  403. ================
  404. */
  405. void() W_FireRocket =
  406. {
  407.     local   entity missile, mpuff;
  408.     
  409.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  410.     
  411.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  412.  
  413.     self.punchangle_x = -2;
  414.  
  415.     missile = spawn ();
  416.     missile.owner = self;
  417.     missile.movetype = MOVETYPE_FLYMISSILE;
  418.     missile.solid = SOLID_BBOX;
  419.     missile.classname = "Rocket";
  420.     
  421. // set missile speed    
  422.  
  423.     makevectors (self.v_angle);
  424.     missile.velocity = aim(self, 1000);
  425.     missile.velocity = missile.velocity * 1000;
  426.     missile.angles = vectoangles(missile.velocity);
  427.     
  428.     missile.touch = T_MissileTouch;
  429.     
  430. // set missile duration
  431.     missile.nextthink = time + 5;
  432.     missile.think = SUB_Remove;
  433.  
  434.     setmodel (missile, "progs/missile.mdl");
  435.     setsize (missile, '0 0 0', '0 0 0');            
  436.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  437. };
  438.  
  439. /*
  440. ===============================================================================
  441.  
  442. LIGHTNING
  443.  
  444. ===============================================================================
  445. */
  446.  
  447. /*
  448. =================
  449. LightningDamage
  450. =================
  451. */
  452. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  453. {
  454.     local entity            e1, e2;
  455.     local vector            f;
  456.     
  457.     f = p2 - p1;
  458.     normalize (f);
  459.     f_x = 0 - f_y;
  460.     f_y = f_x;
  461.     f_z = 0;
  462.     f = f*16;
  463.  
  464.     e1 = e2 = world;
  465.  
  466.     traceline (p1, p2, FALSE, self);
  467.     if (trace_ent.takedamage)
  468.     {
  469.         particle (trace_endpos, '0 0 100', 225, damage*4);
  470.         T_Damage (trace_ent, from, from, damage);
  471.         if (self.classname == "player")
  472.         {
  473.             if (other.classname == "player")
  474.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  475.         }
  476.     }
  477.     e1 = trace_ent;
  478.  
  479.     traceline (p1 + f, p2 + f, FALSE, self);
  480.     if (trace_ent != e1 && trace_ent.takedamage)
  481.     {
  482.         particle (trace_endpos, '0 0 100', 225, damage*4);
  483.         T_Damage (trace_ent, from, from, damage);
  484.     }
  485.     e2 = trace_ent;
  486.  
  487.     traceline (p1 - f, p2 - f, FALSE, self);
  488.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  489.     {
  490.         particle (trace_endpos, '0 0 100', 225, damage*4);
  491.         T_Damage (trace_ent, from, from, damage);
  492.     }
  493. };
  494.  
  495.  
  496. void() W_FireLightning =
  497. {
  498.     local   vector          org;
  499.  
  500.     if (self.ammo_cells < 1)
  501.     {
  502.         self.weapon = W_BestWeapon ();
  503.         W_SetCurrentAmmo ();
  504.         return;
  505.     }
  506.  
  507. // explode if under water
  508.     if (self.waterlevel > 1)
  509.     {
  510.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  511.         self.ammo_cells = 0;
  512.         W_SetCurrentAmmo ();
  513.         return;
  514.     }
  515.  
  516.     if (self.t_width < time)
  517.     {
  518.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  519.         self.t_width = time + 0.6;
  520.     }
  521.     self.punchangle_x = -2;
  522.  
  523.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  524.  
  525.     org = self.origin + '0 0 16';
  526.     
  527.     traceline (org, org + v_forward*600, TRUE, self);
  528.  
  529.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  530.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  531.     WriteEntity (MSG_BROADCAST, self);
  532.     WriteCoord (MSG_BROADCAST, org_x);
  533.     WriteCoord (MSG_BROADCAST, org_y);
  534.     WriteCoord (MSG_BROADCAST, org_z);
  535.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  536.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  537.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  538.  
  539.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  540. };
  541.  
  542.  
  543. //=============================================================================
  544.  
  545.  
  546. void() GrenadeExplode =
  547. {
  548.     T_RadiusDamage (self, self.owner, 120, world);
  549.  
  550.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  551.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  552.     WriteCoord (MSG_BROADCAST, self.origin_x);
  553.     WriteCoord (MSG_BROADCAST, self.origin_y);
  554.     WriteCoord (MSG_BROADCAST, self.origin_z);
  555.  
  556.     BecomeExplosion ();
  557. };
  558.  
  559. void() GrenadeTouch =
  560. {
  561.     if (other == self.owner)
  562.         return;         // don't explode on owner
  563.     if (other.takedamage == DAMAGE_AIM)
  564.     {
  565.         GrenadeExplode();
  566.         return;
  567.     }
  568.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  569.     if (self.velocity == '0 0 0')
  570.         self.avelocity = '0 0 0';
  571. };
  572.  
  573. /*
  574. ================
  575. W_FireGrenade
  576. ================
  577. */
  578. void() W_FireGrenade =
  579. {
  580.     local   entity missile, mpuff;
  581.     
  582.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  583.     
  584.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  585.  
  586.     self.punchangle_x = -2;
  587.  
  588.     missile = spawn ();
  589.     missile.owner = self;
  590.     missile.movetype = MOVETYPE_BOUNCE;
  591.     missile.solid = SOLID_BBOX;
  592.     missile.classname = "grenade";
  593.         
  594. // set missile speed    
  595.  
  596.     makevectors (self.v_angle);
  597.  
  598.     if (self.v_angle_x)
  599.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  600.     else
  601.     {
  602.         missile.velocity = aim(self, 10000);
  603.         missile.velocity = missile.velocity * 600;
  604.         missile.velocity_z = 200;
  605.     }
  606.  
  607.     missile.avelocity = '300 300 300';
  608.  
  609.     missile.angles = vectoangles(missile.velocity);
  610.     
  611.     missile.touch = GrenadeTouch;
  612.     
  613. // set missile duration
  614.     missile.nextthink = time + 2.5;
  615.     missile.think = GrenadeExplode;
  616.  
  617.     setmodel (missile, "progs/grenade.mdl");
  618.     setsize (missile, '0 0 0', '0 0 0');            
  619.     setorigin (missile, self.origin);
  620. };
  621.  
  622.  
  623. //=============================================================================
  624.  
  625. void() spike_touch;
  626. void() superspike_touch;
  627.  
  628.  
  629. /*
  630. ===============
  631. launch_spike
  632.  
  633. Used for both the player and the ogre
  634. ===============
  635. */
  636. void(vector org, vector dir) launch_spike =
  637. {
  638.     newmis = spawn ();
  639.     newmis.owner = self;
  640.     newmis.movetype = MOVETYPE_FLYMISSILE;
  641.     newmis.solid = SOLID_BBOX;
  642.  
  643.     newmis.angles = vectoangles(dir);
  644.     
  645.     newmis.touch = spike_touch;
  646.     newmis.classname = "spike";
  647.     newmis.think = SUB_Remove;
  648. // Bump the nail's lifespan up to 11 seconds(?),so it will stick for a bit        
  649.     newmis.nextthink = time + 11;
  650.     setmodel (newmis, "progs/spike.mdl");
  651.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  652.     setorigin (newmis, org);
  653.  
  654.     newmis.velocity = dir * 1000;
  655. };
  656.  
  657. void() W_FireSuperSpikes =
  658. {
  659.     local vector    dir;
  660.     local entity    old;
  661.     
  662.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  663.     self.attack_finished = time + 0.2;
  664.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  665.     dir = aim (self, 1000);
  666.     launch_spike (self.origin + '0 0 16', dir);
  667.     newmis.touch = superspike_touch;
  668.     setmodel (newmis, "progs/s_spike.mdl");
  669.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  670.     self.punchangle_x = -2;
  671. };
  672.  
  673. void(float ox) W_FireSpikes =
  674. {
  675.     local vector    dir;
  676.     local entity    old;
  677.     
  678.     makevectors (self.v_angle);
  679.     
  680.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  681.     {
  682.         W_FireSuperSpikes ();
  683.         return;
  684.     }
  685.  
  686.     if (self.ammo_nails < 1)
  687.     {
  688.         self.weapon = W_BestWeapon ();
  689.         W_SetCurrentAmmo ();
  690.         return;
  691.     }
  692.  
  693.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  694.     self.attack_finished = time + 0.2;
  695.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  696.     dir = aim (self, 1000);
  697.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  698.  
  699.     self.punchangle_x = -2;
  700. };
  701.  
  702.  
  703.  
  704. .float hit_z;
  705. void() spike_touch =
  706. {
  707. local float rand;
  708.     if (other == self.owner)
  709.         return;
  710.  
  711.     if (other.solid == SOLID_TRIGGER)
  712.         return; // trigger field, do nothing
  713.  
  714.     if (pointcontents(self.origin) == CONTENT_SKY)
  715.     {
  716.         remove(self);
  717.         return;
  718.     }
  719.     
  720. // hit something that bleeds
  721.     if (other.takedamage)
  722.     {
  723.         spawn_touchblood (9);
  724.         T_Damage (other, self, self.owner, 9);
  725.         remove(self);
  726.     }
  727.     else
  728.     {
  729.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  730.         
  731.         if (self.classname == "wizspike")
  732.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  733.         else if (self.classname == "knightspike")
  734.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  735.         else
  736.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  737.         WriteCoord (MSG_BROADCAST, self.origin_x);
  738.         WriteCoord (MSG_BROADCAST, self.origin_y);
  739.         WriteCoord (MSG_BROADCAST, self.origin_z);
  740.     }
  741.  
  742. /*
  743. DO NOT let the nail remove itself. This section of code is only executed
  744. when the nail has hit a wall, floor, or plat. These are places we want the 
  745. nail to stick, so we comment out the REMOVE(SELF); function call
  746. */
  747.     self.velocity='0 0 0'; // make the nail stop!
  748.     remove(self);
  749.  
  750. };
  751.  
  752. void() superspike_touch =
  753. {
  754. local float rand;
  755.     if (other == self.owner)
  756.         return;
  757.  
  758.     if (other.solid == SOLID_TRIGGER)
  759.         return; // trigger field, do nothing
  760.  
  761.     if (pointcontents(self.origin) == CONTENT_SKY)
  762.     {
  763.         remove(self);
  764.         return;
  765.     }
  766.     
  767. // hit something that bleeds
  768.     if (other.takedamage)
  769.     {
  770.         spawn_touchblood (18);
  771.         T_Damage (other, self, self.owner, 18);
  772.     }
  773.     else
  774.     {
  775.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  776.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  777.         WriteCoord (MSG_BROADCAST, self.origin_x);
  778.         WriteCoord (MSG_BROADCAST, self.origin_y);
  779.         WriteCoord (MSG_BROADCAST, self.origin_z);
  780.     }
  781.  
  782.     remove(self);
  783.  
  784. };
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791. /*========================================================================
  792. BOUNCING FRAGMENTATION GRENADE - Version .9
  793. 7/28/96 - Steve Bond  email:wedge@nuc.net
  794. http://www.nuc.net/quake
  795. =======================================================================*/
  796.  
  797. //This code segment handles the impact of shrapnel
  798. //this is merely id's superspike_touch code, reworked
  799. void() shrapnel_touch =
  800. {
  801. local float rand;
  802. // has the shrapnel hit a switch? 
  803.     if (other.solid == SOLID_TRIGGER)
  804.         return; // trigger field, do nothing
  805.  
  806. // has the shrapnel hit the sky?
  807.     if (pointcontents(self.origin) == CONTENT_SKY)
  808.     {
  809.         remove(self);
  810.         return;
  811.     }
  812.     
  813. // has the shrapnel hit a living thing?
  814.     if (other.takedamage)
  815.     {
  816.         spawn_touchblood (18);
  817.         T_Damage (other, self, self.owner, 18);
  818.     }
  819.     else
  820.     {
  821.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  822.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  823.         WriteCoord (MSG_BROADCAST, self.origin_x);
  824.         WriteCoord (MSG_BROADCAST, self.origin_y);
  825.         WriteCoord (MSG_BROADCAST, self.origin_z);
  826.     }
  827.  
  828. };
  829.  
  830. /*
  831. Code to spawn ONE randomly directed piece of shrapnel
  832. this is id's launch_spike code, reworked
  833. Pass a vector to this function to determine the shrap's origin
  834. */
  835. void (vector org, float spin, entity shooter) launch_shrapnel=
  836. {
  837.     local float xdir,ydir,zdir;
  838.     
  839. //Assign a random direction for the shrapnel to fly in
  840.     xdir = 110 * random() - 55;
  841.     ydir = 110 * random() - 55;
  842.     zdir = 50 * random() - 25;
  843.  
  844.     newmis = spawn ();
  845.     newmis.owner = shooter;
  846.     newmis.movetype = MOVETYPE_BOUNCE;
  847.     self.touch = SUB_Null;
  848.     newmis.solid = SOLID_BBOX;
  849.  
  850.     newmis.touch = shrapnel_touch;
  851.     newmis.classname = "spike";
  852.     newmis.think =     ShrapnelExplode;
  853.     
  854. // this is how many seconds(?) the nails can exist.        
  855.     newmis.nextthink = time + 0.75;
  856.     
  857. // speed at which to move the shrapnel        
  858.     newmis.velocity_x = xdir * 5;
  859.     newmis.velocity_y = ydir * 5;
  860.     newmis.velocity_z = zdir * 10;
  861.  
  862. /*
  863. as best I can figure, AVELOCITY means "attitude velocity"        
  864. or something thereabouts. Anyway, it makes shit spin on 
  865. the x,y,z axes by the given velocity for each axis. In this 
  866. case, it makes the shrapnel spin in flight. Good stuff.
  867. this segment assigns one of five preset attitudes for 
  868. each piece of shrapnel, based on the number passed to the
  869. function.
  870. */        
  871.     if (spin == 0)
  872.     newmis.avelocity='250 300 400';
  873.     if (spin == 1)
  874.     newmis.avelocity='400 250 300';
  875.     if (spin == 2)
  876.     newmis.avelocity='300 400 250';
  877.     if (spin == 3)
  878.     newmis.avelocity='300 300 300';
  879.     if (spin == 4) 
  880.     newmis.avelocity='400 250 400';
  881.  
  882.     setmodel (newmis, "progs/grenade.mdl");
  883.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
  884.     setorigin (newmis, org);
  885. };
  886.  
  887. // This code segment detonates the 'second stage' of the grenade
  888. // (After it has popped up)
  889. void()  BouncerExplode =
  890. {
  891.     
  892. // Do the damage
  893.     T_RadiusDamage (self, self.owner, 120, world);
  894. // Tell the network
  895.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  896.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  897.     WriteCoord (MSG_BROADCAST, self.origin_x);
  898.     WriteCoord (MSG_BROADCAST, self.origin_y);
  899.     WriteCoord (MSG_BROADCAST, self.origin_z);
  900.  
  901. // Let Quake handle the explosion and deallocation of the grenade        
  902.     self.solid=SOLID_NOT;
  903.     BecomeExplosion ();
  904.  
  905. // Launch a hail (20 pieces) of shrapnel
  906.     launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
  907.     launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
  908.     launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
  909.     launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
  910.     launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
  911.     launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
  912.     launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
  913.     launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
  914.     launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
  915.     launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
  916.     
  917. };
  918.  
  919. /*
  920. This code segment makes the 'first stage' of the bouncer pop upward
  921. after it's time has expired.
  922. */
  923. void() BouncerTouch;
  924. void() BouncerPopUp=
  925. {
  926.     local entity missile, mpuff;
  927.  
  928. // Make the grenade stop
  929.     self.movetype=MOVETYPE_NONE;
  930.     self.velocity='0 0 0';
  931. // Draw a tiny explosion (no particles)        
  932.     setmodel (self, "progs/s_explod.spr");
  933.     s_explode1 ();
  934. // Make the :FOOMP: grenade launcher sound        
  935.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  936. // Spawn and animate the 'second stage'
  937.     missile = spawn ();
  938.     missile.owner = self.owner;
  939.     missile.movetype = MOVETYPE_BOUNCE;
  940.     missile.solid = SOLID_BBOX;
  941.     missile.classname = "grenade";
  942. // Set speed
  943.     missile.velocity = '0 0 650';
  944.     missile.angles = vectoangles(missile.velocity);
  945.     missile.touch = BouncerTouch;
  946. // Set Duration
  947.     missile.nextthink = time + 1;
  948.     missile.think = BouncerExplode;
  949.  
  950.     setmodel (missile, "progs/missile.mdl");
  951.     setsize (missile, '0 0 0', '0 0 0');
  952.     setorigin (missile, self.origin);
  953. };
  954.  
  955. // This code segment handles collisions for the 'first stage'
  956. // Of the grenade (after launch and before popup)
  957.  
  958. void() BouncerTouch =
  959. {
  960. //Did the grenade hit a 'living' thing?
  961.     if (other.takedamage)
  962.     {
  963. // yes, so play the bounce sound
  964.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  965. // now, exit the function without cause damage to the thing        
  966.     return;
  967.     }
  968.  
  969. // This controls what happens when the grenade hits walls, etz        
  970. // It just plays the sound and bounces on
  971.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  972.     if (self.velocity == '0 0 0')
  973.         self.avelocity = '0 0 0';
  974. };
  975.  
  976. /*
  977. This code segment handles the launching of the Bouncing Fragmentation Grenade
  978. this is a reworked copy of id's W_launchgrenade code
  979. */
  980. void() W_LaunchBouncer =
  981. {
  982. // If player doesn't have 3 or more rockets, don't launch
  983.     if ((self.ammo_rockets < 5) || !(self.weapon & (IT_GRENADE_LAUNCHER | IT_FIREWALL | IT_BOMB)))
  984.     {
  985.     return;
  986.     }
  987.  
  988.     local   entity missile, mpuff;
  989.     
  990. // Take 3 rockets from the player        
  991.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  992.     
  993.     //sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  994. /*
  995. self.punchangle_x (x, y, or z) defines how hard the weapon         
  996. recoils (or 'punches' the player, making the screen shake)
  997. */        
  998.     self.punchangle_x = -2;
  999.  
  1000. // This spawns the grenade - it is all id's standard grenade code        
  1001.     missile = spawn ();
  1002.     missile.owner = self;
  1003.     missile.movetype = MOVETYPE_BOUNCE;
  1004.     missile.solid = SOLID_BBOX;
  1005.     missile.classname = "grenade";
  1006.         
  1007. // set missile speed    
  1008.  
  1009.     makevectors (self.v_angle);
  1010.  
  1011.     if (self.v_angle_x)
  1012.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  1013.     else
  1014.     {
  1015.         missile.velocity = aim(self, 10000);
  1016.         missile.velocity = missile.velocity * 600;
  1017.         missile.velocity_z = 200;
  1018.     }
  1019.  
  1020.     missile.avelocity = '300 300 300';
  1021.  
  1022.     missile.angles = vectoangles(missile.velocity);
  1023.     
  1024. // if the grenade touches anything, BouncerTouch() is called        
  1025.     missile.touch = BouncerTouch;
  1026.     
  1027. // Grenade has a maximum lifespan of 1.5 (seconds?)
  1028. // set missile duration
  1029.     missile.nextthink = time + 1;
  1030.     
  1031. // when the grenade's lifespan has expired, BouncerPopUp() is called        
  1032.     missile.think = BouncerPopUp;
  1033.  
  1034.     setmodel (missile, "progs/grenade.mdl");
  1035.     setsize (missile, '0 0 0', '0 0 0');            
  1036.     setorigin (missile, self.origin);
  1037. //    sprint(self,"Gib 'em!\n");
  1038. };
  1039. /*
  1040. ===============================================================================
  1041. End of Bouncing Fragmentation Grenade code.
  1042. ===============================================================================
  1043. */
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050. /*
  1051.  
  1052. PLAYER WEAPON USE
  1053.  
  1054. ===============================================================================
  1055. */
  1056.  
  1057. void() W_SetCurrentAmmo =
  1058. {
  1059.     player_run ();          // get out of any weapon firing states
  1060.  
  1061.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  1062.     
  1063.     if (self.weapon == IT_AXE)
  1064.     {
  1065.         self.currentammo = 0;
  1066.         self.weaponmodel = "progs/v_axe.mdl";
  1067.         self.weaponframe = 0;
  1068.     }
  1069.     else if (self.weapon == IT_SHOTGUN)
  1070.     {
  1071.         self.currentammo = self.ammo_shells;
  1072.         self.weaponmodel = "progs/v_shot.mdl";
  1073.         self.weaponframe = 0;
  1074.         self.items = self.items | IT_SHELLS;
  1075.     }
  1076.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1077.     {
  1078.         self.currentammo = self.ammo_shells;
  1079.         self.weaponmodel = "progs/v_shot2.mdl";
  1080.         self.weaponframe = 0;
  1081.         self.items = self.items | IT_SHELLS;
  1082.     }
  1083.     else if (self.weapon == IT_NAILGUN)
  1084.     {
  1085.         self.currentammo = self.ammo_nails;
  1086.         self.weaponmodel = "progs/v_nail.mdl";
  1087.         self.weaponframe = 0;
  1088.         self.items = self.items | IT_NAILS;
  1089.     }
  1090.     else if (self.weapon == IT_SUPER_NAILGUN)
  1091.     {
  1092.         self.currentammo = self.ammo_nails;
  1093.         self.weaponmodel = "progs/v_nail2.mdl";
  1094.         self.weaponframe = 0;
  1095.         self.items = self.items | IT_NAILS;
  1096.     }
  1097.     else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_FIREWALL) || (self.weapon == IT_BOMB))
  1098.     {
  1099.         self.currentammo = self.ammo_rockets;
  1100.         self.weaponmodel = "progs/v_rock.mdl";
  1101.         self.weaponframe = 0;
  1102.         self.items = self.items | IT_ROCKETS;
  1103.     }
  1104.     else if (self.weapon == IT_ROCKET_LAUNCHER || (self.weapon == IT_GIBGUN) || (self.weapon == IT_FLASH))
  1105.     {
  1106.         self.currentammo = self.ammo_rockets;
  1107.         self.weaponmodel = "progs/v_rock2.mdl";
  1108.         self.weaponframe = 0;
  1109.         self.items = self.items | IT_ROCKETS;
  1110.     }
  1111.     else if (self.weapon == IT_LIGHTNING)
  1112.     {
  1113.         self.currentammo = self.ammo_cells;
  1114.         self.weaponmodel = "progs/v_light.mdl";
  1115.         self.weaponframe = 0;
  1116.         self.items = self.items | IT_CELLS;
  1117.     }
  1118.     else
  1119.     {
  1120.         self.currentammo = 0;
  1121.         self.weaponmodel = "";
  1122.         self.weaponframe = 0;
  1123.     }
  1124. };
  1125.  
  1126. float() W_BestWeapon =
  1127. {
  1128.     local   float   it;
  1129.     
  1130.     it = self.items;
  1131.  
  1132.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  1133.         return IT_LIGHTNING;
  1134.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  1135.         return IT_SUPER_NAILGUN;
  1136.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  1137.         return IT_SUPER_SHOTGUN;
  1138.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  1139.         return IT_NAILGUN;
  1140.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  1141.         return IT_SHOTGUN;
  1142.         
  1143. /*
  1144.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  1145.         return IT_ROCKET_LAUNCHER;
  1146.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  1147.         return IT_GRENADE_LAUNCHER;
  1148.  
  1149. */
  1150.  
  1151.     return IT_AXE;
  1152. };
  1153.  
  1154. float() W_CheckNoAmmo =
  1155. {
  1156.     if (self.currentammo > 0)
  1157.         return TRUE;
  1158.  
  1159.     if (self.weapon == IT_AXE)
  1160.         return TRUE;
  1161.     
  1162.     self.weapon = W_BestWeapon ();
  1163.  
  1164.     W_SetCurrentAmmo ();
  1165.     
  1166. // drop the weapon down
  1167.     return FALSE;
  1168. };
  1169.  
  1170. /*
  1171. ============
  1172. W_Attack
  1173.  
  1174. An attack impulse can be triggered now
  1175. ============
  1176. */
  1177. void()  player_axe1;
  1178. void()  player_axeb1;
  1179. void()  player_axec1;
  1180. void()  player_axed1;
  1181. void()  player_shot1;
  1182. void()  player_nail1;
  1183. void()  player_light1;
  1184. void()  player_rocket1;
  1185.  
  1186. void() W_Attack =
  1187. {
  1188.     local   float   r;
  1189.  
  1190.     if (!W_CheckNoAmmo ())
  1191.         return;
  1192.  
  1193.     makevectors     (self.v_angle);                 // calculate forward angle for velocity
  1194.     self.show_hostile = time + 1;   // wake monsters up
  1195.  
  1196.     if (self.weapon == IT_AXE)
  1197.     {
  1198.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1199.         r = random();
  1200.         if (r < 0.25)
  1201.             player_axe1 ();
  1202.         else if (r<0.5)
  1203.             player_axeb1 ();
  1204.         else if (r<0.75)
  1205.             player_axec1 ();
  1206.         else
  1207.             player_axed1 ();
  1208.         self.attack_finished = time + 0.5;
  1209.     }
  1210.     else if (self.weapon == IT_SHOTGUN)
  1211.     {
  1212.         player_shot1 ();
  1213.         W_FireShotgun ();
  1214.         self.attack_finished = time + 0.5;
  1215.     }
  1216.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1217.     {
  1218.         player_shot1 ();
  1219.         W_FireSuperShotgun ();
  1220.         self.attack_finished = time + 0.7;
  1221.     }
  1222.     else if (self.weapon == IT_NAILGUN)
  1223.     {
  1224.         player_nail1 ();
  1225.     }
  1226.     else if (self.weapon == IT_SUPER_NAILGUN)
  1227.     {
  1228.         player_nail1 ();
  1229.     }
  1230.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1231.     {
  1232.         player_rocket1();
  1233.         W_FireGrenade();
  1234.         self.attack_finished = time + 0.6;
  1235.     }
  1236.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1237.     {
  1238.         player_rocket1();
  1239.         W_FireRocket();
  1240.         self.attack_finished = time + 0.8;
  1241.     }
  1242.     else if (self.weapon == IT_LIGHTNING)
  1243.     {
  1244.         player_light1();
  1245.         self.attack_finished = time + 0.1;
  1246.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1247.     }
  1248.     else if (self.weapon == IT_FIREWALL)
  1249.     {
  1250.         W_LaunchBouncer();
  1251.         self.attack_finished = time + 0.4;
  1252.     }
  1253.     else if (self.weapon == IT_BOMB)
  1254.     {
  1255.         W_FireBomb();
  1256.         self.attack_finished = time + 0.8;
  1257.     }    
  1258.     else if (self.weapon == IT_GIBGUN)
  1259.     {
  1260.         W_FireGIBGUN();
  1261.         self.attack_finished = time + 0.4;
  1262.     }    
  1263.     else if (self.weapon == IT_FLASH)
  1264.     {
  1265.         W_FireFLASH();
  1266.         self.attack_finished = time + 1;
  1267.     }    
  1268. };
  1269.  
  1270. /*
  1271. ============
  1272. W_ChangeWeapon
  1273.  
  1274. ============
  1275. */
  1276. void() W_ChangeWeapon =
  1277. {
  1278.     local   float   it, am, fl;
  1279.     
  1280.     it = self.items;
  1281.     am = 0;
  1282.     
  1283.     if (self.impulse == 1)
  1284.     {
  1285.         fl = IT_AXE;
  1286.     }
  1287.     else if (self.impulse == 2)
  1288.     {
  1289.         fl = IT_SHOTGUN;
  1290.         if (self.ammo_shells < 1)
  1291.             am = 1;
  1292.     }
  1293.     else if (self.impulse == 3)
  1294.     {
  1295.         fl = IT_SUPER_SHOTGUN;
  1296.         if (self.ammo_shells < 2)
  1297.             am = 1;
  1298.     }               
  1299.     else if (self.impulse == 4)
  1300.     {
  1301.         fl = IT_NAILGUN;
  1302.         if (self.ammo_nails < 1)
  1303.             am = 1;
  1304.     }
  1305.     else if (self.impulse == 5)
  1306.     {
  1307.         fl = IT_SUPER_NAILGUN;
  1308.         if (self.ammo_nails < 2)
  1309.             am = 1;
  1310.     }
  1311.     else if (self.impulse == 6)
  1312.     {
  1313.         if (self.weapon == IT_GRENADE_LAUNCHER)
  1314.         { 
  1315.             self.weapon = IT_FIREWALL;
  1316.             centerprint(self,"Firewall mode\n");
  1317.             return;
  1318.         } 
  1319.         if (self.weapon == IT_FIREWALL)
  1320.         {
  1321.             self.weapon = IT_BOMB;
  1322.             centerprint(self,"Proximity mine mode\n");
  1323.             return;
  1324.         }  
  1325.  
  1326.         fl = IT_GRENADE_LAUNCHER;
  1327.         if (self.ammo_rockets < 1)
  1328.             am = 1;
  1329.         if (!am) centerprint(self,"Grenade Launcher Mode\n");
  1330.     }
  1331.     else if (self.impulse == 7)
  1332.     {
  1333.         if (self.weapon == IT_ROCKET_LAUNCHER)
  1334.         { 
  1335.             self.weapon = IT_GIBGUN;
  1336.             centerprint(self,"Gibgun mode\n");
  1337.             return;
  1338.         } 
  1339.         if (self.weapon == IT_GIBGUN)
  1340.         { 
  1341.             self.weapon = IT_FLASH;
  1342.             centerprint(self,"Flashgun mode\n");
  1343.             return;
  1344.         } 
  1345.         
  1346.         fl = IT_ROCKET_LAUNCHER;
  1347.         if (self.ammo_rockets < 1)
  1348.             am = 1;
  1349.         if (!am) centerprint(self,"Rocket Launcher Mode\n");
  1350.     }
  1351.     else if (self.impulse == 8)
  1352.     {
  1353.         fl = IT_LIGHTNING;
  1354.         if (self.ammo_cells < 1)
  1355.             am = 1;
  1356.     }
  1357.  
  1358.     self.impulse = 0;
  1359.     
  1360.     if (!(self.items & fl))
  1361.     {       // don't have the weapon or the ammo
  1362.         sprint (self, "no weapon.\n");
  1363.         return;
  1364.     }
  1365.     
  1366.     if (am)
  1367.     {       // don't have the ammo
  1368.         sprint (self, "not enough ammo.\n");
  1369.         return;
  1370.     }
  1371.  
  1372. //
  1373. // set weapon, set ammo
  1374. //
  1375.     self.weapon = fl;               
  1376.     W_SetCurrentAmmo ();
  1377. };
  1378.  
  1379. /*
  1380. ============
  1381. CheatCommand
  1382. ============
  1383. */
  1384. void() CheatCommand =
  1385. {
  1386.     if (deathmatch || coop)
  1387.         return;
  1388.  
  1389.     self.ammo_rockets = 100;
  1390.     self.ammo_nails = 200;
  1391.     self.ammo_shells = 100;
  1392.     self.items = self.items | 
  1393.         IT_AXE |
  1394.         IT_SHOTGUN |
  1395.         IT_SUPER_SHOTGUN |
  1396.         IT_NAILGUN |
  1397.         IT_SUPER_NAILGUN |
  1398.         IT_GRENADE_LAUNCHER |
  1399.         IT_ROCKET_LAUNCHER |
  1400.         IT_KEY1 | IT_KEY2;
  1401.  
  1402.     self.ammo_cells = 200;
  1403.     self.items = self.items | IT_LIGHTNING;
  1404.  
  1405.     self.weapon = IT_ROCKET_LAUNCHER;
  1406.     self.impulse = 0;
  1407.     W_SetCurrentAmmo ();
  1408. };
  1409.  
  1410. /*
  1411. ============
  1412. CycleWeaponCommand
  1413.  
  1414. Go to the next weapon with ammo
  1415. ============
  1416. */
  1417. void() CycleWeaponCommand =
  1418. {
  1419.     local   float   it, am;
  1420.     
  1421.     it = self.items;
  1422.     self.impulse = 0;
  1423.     
  1424.     while (1)
  1425.     {
  1426.         am = 0;
  1427.  
  1428.         if (self.weapon == IT_LIGHTNING)
  1429.         {
  1430.             self.weapon = IT_AXE;
  1431.         }
  1432.         else if (self.weapon == IT_AXE)
  1433.         {
  1434.             self.weapon = IT_SHOTGUN;
  1435.             if (self.ammo_shells < 1)
  1436.                 am = 1;
  1437.         }
  1438.         else if (self.weapon == IT_SHOTGUN)
  1439.         {
  1440.             self.weapon = IT_SUPER_SHOTGUN;
  1441.             if (self.ammo_shells < 2)
  1442.                 am = 1;
  1443.         }               
  1444.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1445.         {
  1446.             self.weapon = IT_NAILGUN;
  1447.             if (self.ammo_nails < 1)
  1448.                 am = 1;
  1449.         }
  1450.         else if (self.weapon == IT_NAILGUN)
  1451.         {
  1452.             self.weapon = IT_SUPER_NAILGUN;
  1453.             if (self.ammo_nails < 2)
  1454.                 am = 1;
  1455.         }
  1456.         else if (self.weapon == IT_SUPER_NAILGUN)
  1457.         {
  1458.             self.weapon = IT_GRENADE_LAUNCHER;
  1459.             if (self.ammo_rockets < 1)
  1460.                 am = 1;
  1461.         }
  1462.         else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_FIREWALL) || (self.weapon == IT_BOMB))
  1463.         {
  1464.             self.weapon = IT_ROCKET_LAUNCHER;
  1465.             if (self.ammo_rockets < 1)
  1466.                 am = 1;
  1467.         }
  1468.         else if ((self.weapon == IT_ROCKET_LAUNCHER) || (self.weapon == IT_GIBGUN) || (self.weapon == IT_FLASH))
  1469.         {
  1470.             self.weapon = IT_LIGHTNING;
  1471.             if (self.ammo_cells < 1)
  1472.                 am = 1;
  1473.         }
  1474.     
  1475.         if ( (self.items & self.weapon) && am == 0)
  1476.         {
  1477.             W_SetCurrentAmmo ();
  1478.             return;
  1479.         }
  1480.     }
  1481.  
  1482. };
  1483.  
  1484. /*
  1485. ============
  1486. ServerflagsCommand
  1487.  
  1488. Just for development
  1489. ============
  1490. */
  1491. void() ServerflagsCommand =
  1492. {
  1493.     serverflags = serverflags * 2 + 1;
  1494. };
  1495.  
  1496. void() QuadCheat =
  1497. {
  1498.     if (deathmatch || coop)
  1499.         return;
  1500.     self.super_time = 1;
  1501.     self.super_damage_finished = time + 30;
  1502.     self.items = self.items | IT_QUAD;
  1503.     dprint ("quad cheat\n");
  1504. };
  1505.  
  1506. /*
  1507. ============
  1508. ImpulseCommands
  1509.  
  1510. ============
  1511. */
  1512. void() ImpulseCommands =
  1513. {
  1514.     if (self.impulse >= 1 && self.impulse <= 8)
  1515.         W_ChangeWeapon ();
  1516.  
  1517.     if (self.impulse == 9)
  1518.         CheatCommand ();
  1519.     if (self.impulse == 10)
  1520.         CycleWeaponCommand ();
  1521.     if (self.impulse == 11)
  1522.         ServerflagsCommand ();
  1523.     
  1524.     // PATCH FOR BOUNCERS
  1525.  
  1526.     if (self.impulse == 20)
  1527.         {
  1528.         W_LaunchBouncer ();
  1529.         self.attack_finished = time + 0.4;
  1530.         }
  1531.     if (self.impulse == 21)
  1532.         {
  1533.         W_FireBomb ();
  1534.         self.attack_finished = time + 0.8;
  1535.         }
  1536.     if (self.impulse == 22)
  1537.         {
  1538.         W_FireGIBGUN ();
  1539.         self.attack_finished = time + 0.4;
  1540.         }
  1541.     if (self.impulse == 23)
  1542.         {
  1543.         W_FireFLASH ();
  1544.         self.attack_finished = time + 1;
  1545.         }
  1546.  
  1547.     if (self.impulse == 255)
  1548.         QuadCheat ();
  1549.         
  1550.     self.impulse = 0;
  1551. };
  1552.  
  1553. /*
  1554. ============
  1555. W_WeaponFrame
  1556.  
  1557. Called every frame so impulse events can be handled as well as possible
  1558. ============
  1559. */
  1560. void() W_WeaponFrame =
  1561. {
  1562.     if (time < self.attack_finished)
  1563.         return;
  1564.  
  1565.     ImpulseCommands ();
  1566.     
  1567. // check for attack
  1568.     if (self.button0)
  1569.     {
  1570.         SuperDamageSound ();
  1571.         W_Attack ();
  1572.     }
  1573. };
  1574.  
  1575. /*
  1576. ========
  1577. SuperDamageSound
  1578.  
  1579. Plays sound if needed
  1580. ========
  1581. */
  1582. void() SuperDamageSound =
  1583. {
  1584.     if (self.super_damage_finished > time)
  1585.     {
  1586.         if (self.super_sound < time)
  1587.         {
  1588.             self.super_sound = time + 1;
  1589.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1590.         }
  1591.     }
  1592.     return;
  1593. };
  1594.  
  1595.  
  1596. /***********************************************************************************
  1597. ================
  1598. W_FireBomb
  1599. ================
  1600. ************************************************************************************/
  1601. void() W_FireBomb =
  1602. {
  1603.     local   entity missile, mpuff;
  1604.  
  1605.     if ((self.ammo_rockets < 5) || !(self.weapon & (IT_GRENADE_LAUNCHER | IT_FIREWALL | IT_BOMB )))
  1606.     {
  1607.         return;
  1608.     }
  1609.  
  1610.  
  1611.     if (bombtimer >0 )
  1612.     {
  1613.         return;
  1614.     }
  1615.     else     bombtimer=1.5;
  1616.  
  1617.  
  1618.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  1619.     
  1620.  
  1621.  
  1622.     self.punchangle_x = -10;
  1623.  
  1624.     missile = spawn ();
  1625.     missile.owner = self;
  1626.     missile.movetype = MOVETYPE_FLY;
  1627.     missile.solid = SOLID_TRIGGER;
  1628.     missile.classname = "Bomb";
  1629.         
  1630. // set missile speed    
  1631.  
  1632.     makevectors (self.v_angle);
  1633.  
  1634.  
  1635.     missile.velocity= '0 0 0';
  1636.     missile.avelocity= '0 0 0';
  1637.     
  1638.     missile.touch = BombTouch;
  1639.     
  1640. // set missile duration
  1641.     missile.nextthink = time + 0.25;
  1642.     missile.think = BombTime;
  1643.  
  1644.     setmodel (missile, "progs/grenade.mdl");
  1645.     setsize (missile, '-48 -48 -4', '48 48 4');            
  1646.     setorigin (missile, self.origin - '0 0 20');
  1647. //    sprint(self,"Better stay the hell clear now\n");
  1648. };
  1649.  
  1650. void() BombTime =
  1651. {
  1652.     bombtimer = bombtimer - 0.25;
  1653.     if (bombtimer)
  1654.         {
  1655.         if (bombtimer == 0.5) self.velocity='0 0 24';
  1656.         sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  1657.         self.nextthink = time + 0.25;
  1658.         self.think = BombTime;
  1659.         } 
  1660.     else
  1661.     {
  1662.         self.nextthink = time + 180;
  1663.         self.think = BecomeExplosion;
  1664.         self.classname = "ArmedBomb";
  1665.         self.velocity='0 0 0';
  1666.         self.avelocity='0 800 800';
  1667.         
  1668.         self.health = 20;
  1669.         self.th_die = BombExplode;
  1670.         self.takedamage = DAMAGE_AIM;
  1671.  
  1672.     }
  1673. };
  1674.  
  1675. void() BombTouch =
  1676. {
  1677.     if (other.takedamage && (self.classname == "ArmedBomb") && (other.classname != "ArmedBomb"))
  1678.     {
  1679.         BombExplode();
  1680.         return;
  1681.     }
  1682.  
  1683. };
  1684.  
  1685. void() BombExplode =
  1686. {
  1687.     T_RadiusDamage (self, self.owner, 120, world);
  1688.  
  1689.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1690.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1691.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1692.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1693.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1694.  
  1695.     BombExplosion ();
  1696. };
  1697.  
  1698. void() BombExplosion =
  1699. {
  1700.     sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
  1701.     self.movetype = MOVETYPE_NONE;
  1702.     self.velocity = '0 0 0';
  1703.     self.touch = SUB_Null;
  1704.     setmodel (self, "progs/s_explod.spr");
  1705.     self.solid = SOLID_NOT;
  1706.     s_explode1 ();
  1707. };
  1708.  
  1709. void() ShrapnelExplode =
  1710. {
  1711.     T_RadiusDamage (self, self.owner, 120, world);
  1712.  
  1713.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1714.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1715.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1716.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1717.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1718.  
  1719.     BecomeExplosion ();
  1720. };
  1721.  
  1722. void() GIBExplode =
  1723. {
  1724.     local entity loser;
  1725.     self.wait = self.wait - 1;
  1726.     loser = self.trigger_field;
  1727.  
  1728.     if ((self.wait == 30) || (self.wait == 20) || (self.wait == 10))     sound (self, CHAN_WEAPON, "player/tornoff2.wav", 1, ATTN_NORM);    
  1729.     if (((self.wait == 35) || (self.wait == 25) || (self.wait == 15)) && (loser.classname == "player"))     sound (self, CHAN_WEAPON, "player/lburn1.wav", 1, ATTN_NORM);    
  1730.  
  1731.     if ((!self.wait) || (loser.health<=10))
  1732.     {
  1733.     T_RadiusDamage (self, self.owner, 120, world);
  1734.  
  1735.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1736.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1737.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1738.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1739.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1740.  
  1741.     BecomeExplosion ();
  1742.     return;
  1743.     }
  1744.  
  1745.     
  1746.     T_Damage (loser, self, self.owner, 2.5 );
  1747.     spawn_touchblood (30);
  1748.  
  1749.     self.origin = loser.origin + '0 0 12';
  1750.     self.nextthink = time + 0.05;
  1751.     self.think = GIBExplode;
  1752.         
  1753. };
  1754.  
  1755. void() T_GIBTouch =
  1756. {
  1757.     local float     damg;
  1758.  
  1759.     if (other == self.owner)
  1760.         return;         // don't explode on owner
  1761.  
  1762.     if (pointcontents(self.origin) == CONTENT_SKY)
  1763.     {
  1764.         remove(self);
  1765.         return;
  1766.     }
  1767.  
  1768.  
  1769.     
  1770.     if (other.takedamage)
  1771.     {
  1772.         sound (self, CHAN_WEAPON, "player/tornoff2.wav", 1, ATTN_NORM);    
  1773.         self.trigger_field = other;
  1774.         self.origin = other.origin + '0 0 12';
  1775.         self.wait = 40;
  1776.  
  1777.         self.nextthink = time + 0.05;
  1778.         self.think = GIBExplode;
  1779.         self.movetype = MOVETYPE_NOCLIP;
  1780.         self.velocity = '0 0 0' ;
  1781.         self.avelocity = '0 0 1000';
  1782.         return;
  1783.     }
  1784.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  1785. //    remove(self);
  1786.     self.nextthink = time + 0.3;
  1787.     self.think = SUB_Remove;
  1788.     self.movetype = MOVETYPE_NOCLIP;
  1789.     self.velocity = ' 0 0 0';
  1790.     self.avelocity = '0 0 1000';
  1791. };
  1792.  
  1793.  
  1794.  
  1795. /*
  1796. ================
  1797. W_FireGIBGUN
  1798. ================
  1799. */
  1800. void() W_FireGIBGUN =
  1801. {
  1802.     if ((self.ammo_rockets < 1) || !(self.weapon & (IT_ROCKET_LAUNCHER | IT_GIBGUN | IT_FLASH)))
  1803.     {
  1804.         return;
  1805.     }
  1806.     local   entity missile, mpuff;
  1807.     
  1808.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  1809.     
  1810.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  1811.  
  1812.     self.punchangle_x = -2;
  1813.  
  1814.     missile = spawn ();
  1815.     missile.owner = self;
  1816.     missile.movetype = MOVETYPE_FLYMISSILE;
  1817.     missile.solid = SOLID_BBOX;
  1818.     missile.classname = "GibGun";
  1819.     
  1820. // set missile speed    
  1821.  
  1822.     makevectors (self.v_angle);
  1823.     missile.velocity = aim(self, 1000);
  1824.     missile.velocity = missile.velocity * 1000;
  1825.     missile.angles = vectoangles(missile.velocity);
  1826.     
  1827.     missile.touch = T_GIBTouch;
  1828.     
  1829. // set missile duration
  1830.     missile.nextthink = time + 5;
  1831.     missile.think = SUB_Remove;
  1832.     setmodel (missile, "progs/missile.mdl");
  1833.     setsize (missile, '0 0 0', '0 0 0');            
  1834.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  1835. };
  1836.  
  1837. /*
  1838. ================
  1839. W_FireFlash
  1840. ================
  1841. */
  1842. void() W_FireFLASH =
  1843. {
  1844.     if ((self.ammo_rockets < 5) || !(self.weapon & (IT_ROCKET_LAUNCHER | IT_GIBGUN | IT_FLASH)))
  1845.     {
  1846.         return;
  1847.     }
  1848.     local   entity missile, mpuff;
  1849.     
  1850.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  1851.     
  1852.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  1853.  
  1854.     self.punchangle_x = -2;
  1855.  
  1856.     missile = spawn ();
  1857.     missile.owner = self;
  1858.     missile.movetype = MOVETYPE_FLYMISSILE;
  1859.     missile.solid = SOLID_BBOX;
  1860.     missile.classname = "Flash";
  1861.     
  1862. // set missile speed    
  1863.  
  1864.     makevectors (self.v_angle);
  1865.     missile.velocity = aim(self, 100000);
  1866.     missile.velocity = missile.velocity * 800;
  1867.     missile.angles = vectoangles(missile.velocity);
  1868.     
  1869.     missile.touch = T_FlashTouch;
  1870.     
  1871. // set missile duration
  1872.     missile.nextthink = time + 5;
  1873.     missile.think = SUB_Remove;
  1874.  
  1875.     setmodel (missile, "progs/missile.mdl");
  1876.     setsize (missile, '0 0 0', '0 0 0');            
  1877.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  1878.  
  1879. };
  1880.  
  1881. void() T_FlashTouch =
  1882. {
  1883.     local float     damg;
  1884.  
  1885.     if (other == self.owner)
  1886.         return;         // don't explode on owner
  1887.  
  1888.     if (pointcontents(self.origin) == CONTENT_SKY)
  1889.     {
  1890.         remove(self);
  1891.         return;
  1892.     }
  1893.     
  1894.     self.effects = self.effects | EF_BRIGHTLIGHT;        
  1895.     damg = 20;
  1896.     
  1897.     if (other.health)
  1898.     {
  1899.         if (other.classname == "monster_shambler")
  1900.             damg = damg * 0.5;      // mostly immune
  1901.         T_Damage (other, self, self.owner, damg );
  1902.     }
  1903.  
  1904.     // don't do radius damage to the other, because all the damage
  1905.     // was done in the impact
  1906.     T_RadiusDamage (self, self.owner, 20, other);
  1907.     T_FlashDamage (self, self.owner,1000, self);
  1908.  
  1909.         sound (self, CHAN_WEAPON, "doors/airdoor2.wav", 1, ATTN_NORM);
  1910.     self.origin = self.origin - 8*normalize(self.velocity);
  1911.     
  1912.  
  1913.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1914.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1915.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1916.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1917.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1918.  
  1919.     BecomeExplosion ();
  1920. };